home *** CD-ROM | disk | FTP | other *** search
/ Disc to the Future 2 / Disc to the Future Part II Programmer's Reference (Wayzata Technology)(6013)(1992).bin / MAC / THINKC / 5 / MACVOGL- / POLYGONS.C < prev    next >
C/C++ Source or Header  |  1992-07-19  |  18KB  |  1,154 lines

  1. #include <stdio.h>
  2. #include "vogl.h"
  3.  
  4. extern    double    cos();
  5. extern    double    sin();
  6.  
  7. #define MAX(x, y)    ((x) > (y) ? (x) : (y))
  8. #define MIN(x, y)    ((x) < (y) ? (x) : (y))
  9. #define ABS(x)        ((x) < 0 ? -(x) : (x))
  10.  
  11. static double    F[6][4], S[6][4], I[4], p[MAXVERTS][4];
  12. static int    nout, first[6], numv;
  13. static long    polymodeflag = PYM_FILL;
  14. static int    ip1[MAXVERTS], ip2[MAXVERTS];
  15.  
  16. /*
  17.  *  Orientation of backfacing polygons(in screen coords)
  18.  */
  19. static    int    clockwise = 1;
  20.  
  21. static void    polyoutline(), polyclip(), shclip(), shclose();
  22. static int    checkbacki(), intersect(), visible();
  23.  
  24. /*
  25.  * concave
  26.  *
  27.  *    signal wether or not polygons are concave (not a lot of use at the moment).
  28.  */
  29. void
  30. concave(yesno)
  31.     Boolean    yesno;
  32. {
  33.     vdevice.concave = yesno;
  34. }
  35.  
  36. /*
  37.  * backface
  38.  *
  39.  *    Turns on culling of backfacing polygons. A polygon is
  40.  * backfacing if it's orientation in *screen* coords is clockwise.
  41.  */
  42. void
  43. backface(onoff)
  44.     int    onoff;
  45. {
  46.     vdevice.attr->a.backface = onoff;
  47.     clockwise = 1;
  48. }
  49.  
  50. /*
  51.  * frontface
  52.  *
  53.  *    Turns on culling of frontfacing polygons. A polygon is
  54.  * frontfacing if it's orientation in *screen* coords is anti-clockwise.
  55.  */
  56. void
  57. frontface(onoff)
  58.     int    onoff;
  59. {
  60.     vdevice.attr->a.backface = onoff;
  61.     clockwise = 0;
  62. }
  63.  
  64. /*
  65.  * polymode
  66.  *
  67.  *    Sets the polygon filling mode - only filled or outlined supported
  68.  */
  69. void
  70. polymode(mode)
  71.     long    mode;
  72. {
  73. /*
  74.  * On older SGI Machines this call used to work... On the newer
  75.  * boxes it doesn't do anything. If you want the old stuff then
  76.  * #define OLD_SGI_BOXES somewhere.
  77.  */
  78. #ifdef OLD_SGI_BOXES
  79.     polymodeflag = mode;
  80. #endif
  81. }
  82.  
  83. /*
  84.  * dopoly
  85.  *
  86.  *    do a transformed polygon with n edges using fill
  87.  */
  88. static void
  89. dopoly(n)
  90.     int    n;
  91. {
  92.     int    i;
  93.     char    buf[100];
  94.  
  95.     if (n > MAXVERTS) {
  96.         sprintf(buf, "dopoly: can't fill a polygon with more than %d vertices", MAXVERTS);
  97.         verror(buf);
  98.     }
  99.  
  100.     if (!vdevice.clipoff) {
  101.         polyclip(n);
  102.     } else {
  103.         nout = n;
  104.         for (i = 0; i < n; i++) {
  105.             ip1[i] = WtoVx(p[i]);
  106.             ip2[i] = WtoVy(p[i]);
  107.         }
  108.     }
  109.  
  110.  
  111.     if (vdevice.attr->a.backface && checkbacki()) {
  112.         vdevice.fill = 0;
  113.         return;
  114.     }
  115.  
  116.     if (vdevice.fill) {
  117.         if (nout > 2) {
  118.             (*vdevice.dev.Vfill)(nout, ip1, ip2);
  119.         }
  120.     } else {
  121.         vdevice.cpVx = ip1[0];
  122.         vdevice.cpVy = ip2[0];
  123.         vdevice.cpVvalid = 0;
  124.         polyoutline(nout, ip1, ip2);
  125.     }
  126.  
  127.     vdevice.fill = 0;
  128. }
  129.  
  130. /*
  131.  * polyoutline
  132.  *
  133.  *    draws a polygon outline from already transformed points.
  134.  */
  135. static void
  136. polyoutline(n, ipx, ipy)
  137.     int    n;
  138.     int    ipx[], ipy[];
  139. {
  140.     int    i;
  141.  
  142.     if (n > 2) {
  143.         for (i = 1; i < n; i++) {
  144.             (*vdevice.dev.Vdraw)(ipx[i], ipy[i]);
  145.  
  146.             vdevice.cpVx = ipx[i];
  147.             vdevice.cpVy = ipy[i];
  148.         }
  149.         (*vdevice.dev.Vdraw)(ipx[0], ipy[0]);
  150.  
  151.         vdevice.cpVx = ipx[0];
  152.         vdevice.cpVy = ipy[0];
  153.     }
  154. }
  155.  
  156. /*
  157.  * polyobj
  158.  *
  159.  *    construct a polygon from a object token list.
  160.  */
  161. void
  162. polyobj(n, dp, fill)
  163.     int    n;
  164.     Token    dp[];
  165.     int    fill;
  166. {
  167.     int    i, j;
  168.     double    vect[4], result[4];
  169.     
  170.     for (i = 0, j = 0; i < n; i++, j += 3) {
  171.         vect[V_X] = dp[j + V_X].f;
  172.         vect[V_Y] = dp[j + V_Y].f;
  173.         vect[V_Z] = dp[j + V_Z].f;
  174.         vect[V_W] = 1;
  175.         multvector(result, vect, vdevice.transmat->m);
  176.         p[i][V_X] = result[V_X];
  177.         p[i][V_Y] = result[V_Y];
  178.         p[i][V_Z] = result[V_Z];
  179.         p[i][V_W] = result[V_W];
  180.     }
  181.  
  182.     if (fill)
  183.         vdevice.fill = polymodeflag;
  184.     else
  185.         vdevice.fill = 0;
  186.  
  187.     dopoly(n);
  188.  
  189.     vdevice.cpW[V_X] = dp[V_X].f;
  190.     vdevice.cpW[V_Y] = dp[V_Y].f;
  191.     vdevice.cpW[V_Z] = dp[V_Z].f;
  192. }
  193.  
  194. /*
  195.  * poly2
  196.  *
  197.  *    construct a polygon from an (x, y) array of points provided by the user.
  198.  */
  199. void
  200. poly2(nv, dp)
  201.     long    nv;
  202.     double    dp[][2];
  203. {
  204.     int    i;
  205.     double    np[MAXVERTS][3];
  206.  
  207.     if (!vdevice.initialised)
  208.         verror("poly2: vogl not initialised");
  209.  
  210.     vdevice.fill = 0;
  211.  
  212.     for (i = 0; i < (int)nv; i++) {
  213.         np[i][V_X] = dp[i][V_X];
  214.         np[i][V_Y] = dp[i][V_Y];
  215.         np[i][V_Z] = 0.0;
  216.     }
  217.  
  218.     poly(nv, np);
  219. }
  220.  
  221. /*
  222.  * poly2i
  223.  *
  224.  *    construct a polygon from an (x, y) array of points provided by the user.
  225.  * Icoord version.
  226.  */
  227. void
  228. poly2i(nv, dp)
  229.     long    nv;
  230.     Icoord    dp[][2];
  231. {
  232.     int    i;
  233.     double    np[MAXVERTS][3];
  234.  
  235.     if (!vdevice.initialised)
  236.         verror("poly2i: vogl not initialised");
  237.  
  238.     vdevice.fill = 0;
  239.  
  240.     for (i = 0; i < (int)nv; i++) {
  241.         np[i][V_X] = dp[i][V_X];
  242.         np[i][V_Y] = dp[i][V_Y];
  243.         np[i][V_Z] = 0.0;
  244.     }
  245.  
  246.     poly(nv, np);
  247. }
  248.  
  249. /*
  250.  * poly2s
  251.  *
  252.  *    construct a polygon from an (x, y) array of points provided by the user.
  253.  * Scoord version.
  254.  */
  255. void
  256. poly2s(nv, dp)
  257.     long    nv;
  258.     Scoord    dp[][2];
  259. {
  260.     int    i;
  261.     double    np[MAXVERTS][3];
  262.  
  263.     if (!vdevice.initialised)
  264.         verror("poly2s: vogl not initialised");
  265.  
  266.     vdevice.fill = 0;
  267.  
  268.     for (i = 0; i < (int)nv; i++) {
  269.         np[i][V_X] = dp[i][V_X];
  270.         np[i][V_Y] = dp[i][V_Y];
  271.         np[i][V_Z] = 0.0;
  272.     }
  273.  
  274.     poly(nv, np);
  275. }
  276.  
  277. /*
  278.  * polyi
  279.  *
  280.  *    construct a polygon from an (x, y, z) array of points provided by the user.
  281.  * Icoord version.
  282.  */
  283. void
  284. polyi(nv, dp)
  285.     long    nv;
  286.     Icoord    dp[][3];
  287. {
  288.     int    i;
  289.     double    np[MAXVERTS][3];
  290.  
  291.     if (!vdevice.initialised)
  292.         verror("polyi: vogl not initialised");
  293.  
  294.     vdevice.fill = 0;
  295.  
  296.     for (i = 0; i < (int)nv; i++) {
  297.         np[i][V_X] = dp[i][V_X];
  298.         np[i][V_Y] = dp[i][V_Y];
  299.         np[i][V_Z] = dp[i][V_Z];
  300.     }
  301.  
  302.     poly(nv, np);
  303. }
  304.  
  305. /*
  306.  * polys
  307.  *
  308.  *    construct a polygon from an (x, y, z) array of points provided by the user.
  309.  * Scoord version.
  310.  */
  311. void
  312. polys(nv, dp)
  313.     long    nv;
  314.     Scoord    dp[][3];
  315. {
  316.     int    i;
  317.     double    np[MAXVERTS][3];
  318.  
  319.     if (!vdevice.initialised)
  320.         verror("poly2s: vogl not initialised");
  321.  
  322.     vdevice.fill = 0;
  323.  
  324.     for (i = 0; i < (int)nv; i++) {
  325.         np[i][V_X] = dp[i][V_X];
  326.         np[i][V_Y] = dp[i][V_Y];
  327.         np[i][V_Z] = dp[i][V_Z];
  328.     }
  329.  
  330.     poly(nv, np);
  331. }
  332.  
  333. /*
  334.  * polf2
  335.  *
  336.  *    construct a filled polygon from an (x, y) array of points provided
  337.  * by the user.
  338.  */
  339. void
  340. polf2(nv, dp)
  341.     long    nv;
  342.     double    dp[][2];
  343. {
  344.     int    i;
  345.     double    np[MAXVERTS][3];
  346.  
  347.     if (!vdevice.initialised)
  348.         verror("polf2: vogl not initialised");
  349.  
  350.     vdevice.fill = polymodeflag;
  351.  
  352.     for (i = 0; i < (int)nv; i++) {
  353.         np[i][V_X] = dp[i][V_X];
  354.         np[i][V_Y] = dp[i][V_Y];
  355.         np[i][V_Z] = 0.0;
  356.     }
  357.  
  358.     poly(nv, np);
  359.  
  360.     vdevice.fill = 0;
  361. }
  362.  
  363. /*
  364.  * polf2i
  365.  *
  366.  *    construct a filled polygon from an (x, y) array of points provided
  367.  * by the user. Icoord version.
  368.  */
  369. void
  370. polf2i(nv, dp)
  371.     long    nv;
  372.     Icoord    dp[][2];
  373. {
  374.     int    i;
  375.     double    np[MAXVERTS][3];
  376.  
  377.     if (!vdevice.initialised)
  378.         verror("polf2i: vogl not initialised");
  379.  
  380.     vdevice.fill = polymodeflag;
  381.  
  382.     for (i = 0; i < (int)nv; i++) {
  383.         np[i][V_X] = dp[i][V_X];
  384.         np[i][V_Y] = dp[i][V_Y];
  385.         np[i][V_Z] = 0.0;
  386.     }
  387.  
  388.     poly(nv, np);
  389.  
  390.     vdevice.fill = 0;
  391. }
  392.  
  393. /*
  394.  * polf2s
  395.  *
  396.  *    construct a filled polygon from an (x, y) array of points provided
  397.  * by the user. Scoord version.
  398.  */
  399. void
  400. polf2s(nv, dp)
  401.     long    nv;
  402.     Scoord    dp[][2];
  403. {
  404.     int    i;
  405.     double    np[MAXVERTS][3];
  406.  
  407.     if (!vdevice.initialised)
  408.         verror("polf2s: vogl not initialised");
  409.  
  410.     vdevice.fill = polymodeflag;
  411.  
  412.     for (i = 0; i < (int)nv; i++) {
  413.         np[i][V_X] = dp[i][V_X];
  414.         np[i][V_Y] = dp[i][V_Y];
  415.         np[i][V_Z] = 0.0;
  416.     }
  417.  
  418.     poly(nv, np);
  419.  
  420.     vdevice.fill = 0;
  421. }
  422.  
  423. /*
  424.  * polfi
  425.  *
  426.  *    construct a filled polygon from an (x, y, z) array of points provided
  427.  * by the user. Icoord version.
  428.  */
  429. void
  430. polfi(nv, dp)
  431.     long    nv;
  432.     Icoord    dp[][3];
  433. {
  434.     int    i;
  435.     double    np[MAXVERTS][3];
  436.  
  437.     if (!vdevice.initialised)
  438.         verror("polfi: vogl not initialised");
  439.  
  440.     vdevice.fill = polymodeflag;
  441.  
  442.     for (i = 0; i < (int)nv; i++) {
  443.         np[i][V_X] = dp[i][V_X];
  444.         np[i][V_Y] = dp[i][V_Y];
  445.         np[i][V_Z] = dp[i][V_Z];
  446.     }
  447.  
  448.     poly(nv, np);
  449.  
  450.     vdevice.fill = 0;
  451. }
  452.  
  453. /*
  454.  * polfs
  455.  *
  456.  *    construct a filled polygon from an (x, y, z) array of points provided
  457.  * by the user. Scoord version.
  458.  */
  459. void
  460. polfs(nv, dp)
  461.     long    nv;
  462.     Scoord    dp[][3];
  463. {
  464.     int    i;
  465.     double    np[MAXVERTS][3];
  466.  
  467.     if (!vdevice.initialised)
  468.         verror("polfs: vogl not initialised");
  469.  
  470.     vdevice.fill = polymodeflag;
  471.  
  472.     for (i = 0; i < (int)nv; i++) {
  473.         np[i][V_X] = dp[i][V_X];
  474.         np[i][V_Y] = dp[i][V_Y];
  475.         np[i][V_Z] = dp[i][V_Z];
  476.     }
  477.  
  478.     poly(nv, np);
  479.  
  480.     vdevice.fill = 0;
  481. }
  482.  
  483. /*
  484.  * poly
  485.  *
  486.  *    construct a polygon from an array of points provided by the user.
  487.  */
  488. void
  489. poly(nv, dp)
  490.     long    nv;
  491.     double    dp[][3];
  492. {
  493.     int    i, j;
  494.     Vector    vect, result;
  495.     Token    *tok;
  496.     int    n = nv;
  497.     
  498.     if (!vdevice.initialised)
  499.         verror("poly: vogl not initialised");
  500.  
  501.     if (vdevice.inobject) {
  502.         tok = newtokens(2 + 3 * n);
  503.         tok[0].i = POLY;
  504.         tok[1].i = n;
  505.         for (i = 0, j = 2; i < n; i++, j += 3) {
  506.             tok[j + V_X].f = dp[i][V_X];
  507.             tok[j + V_Y].f = dp[i][V_Y];
  508.             tok[j + V_Z].f = dp[i][V_Z];
  509.         }
  510.         return;
  511.     }
  512.  
  513.     for (i = 0; i < n; i++) {
  514.         vect[V_X] = dp[i][V_X];
  515.         vect[V_Y] = dp[i][V_Y];
  516.         vect[V_Z] = dp[i][V_Z];
  517.         vect[V_W] = 1;
  518.         multvector(result, vect, vdevice.transmat->m);
  519.         p[i][V_X] = result[V_X];
  520.         p[i][V_Y] = result[V_Y];
  521.         p[i][V_Z] = result[V_Z];
  522.         p[i][V_W] = result[V_W];
  523.     }
  524.  
  525.     dopoly(n);
  526.  
  527.     vdevice.cpW[V_X] = dp[0][V_X];
  528.     vdevice.cpW[V_Y] = dp[0][V_Y];
  529.     vdevice.cpW[V_Z] = dp[0][V_Z];
  530. }
  531.  
  532. /*
  533.  * polf
  534.  *
  535.  *    construct a filled polygon from an array of points provided
  536.  * by the user.
  537.  */
  538. void
  539. polf(nv, dp)
  540.     long    nv;
  541.     double    dp[][3];
  542. {
  543.     int    i, j;
  544.     Vector    vect, result;
  545.     Token    *tok;
  546.     long    n = nv;
  547.     
  548.     if (!vdevice.initialised)
  549.         verror("poly: vogl not initialised");
  550.  
  551.     vdevice.fill = polymodeflag;
  552.  
  553.     if (vdevice.inobject) {
  554.         tok = newtokens(2 + 3 * n);
  555.         tok[0].i = POLYF;
  556.         tok[1].i = n;
  557.         for (i = 0, j = 2; i < n; i++, j += 3) {
  558.             tok[j + V_X].f = dp[i][V_X];
  559.             tok[j + V_Y].f = dp[i][V_Y];
  560.             tok[j + V_Z].f = dp[i][V_Z];
  561.         }
  562.         return;
  563.     }
  564.  
  565.     for (i = 0; i < n; i++) {
  566.         vect[V_X] = dp[i][V_X];
  567.         vect[V_Y] = dp[i][V_Y];
  568.         vect[V_Z] = dp[i][V_Z];
  569.         vect[V_W] = 1;
  570.         multvector(result, vect, vdevice.transmat->m);
  571.         p[i][V_X] = result[V_X];
  572.         p[i][V_Y] = result[V_Y];
  573.         p[i][V_Z] = result[V_Z];
  574.         p[i][V_W] = result[V_W];
  575.     }
  576.  
  577.     dopoly(n);
  578.  
  579.     vdevice.cpW[V_X] = dp[0][V_X];
  580.     vdevice.cpW[V_Y] = dp[0][V_Y];
  581.     vdevice.cpW[V_Z] = dp[0][V_Z];
  582.  
  583.     vdevice.fill = 0;
  584. }
  585.  
  586. /*
  587.  * pmv
  588.  *
  589.  *    set the start position of a polygon
  590.  */
  591. void
  592. pmv(x, y, z)
  593.     double    x, y, z;
  594. {
  595.     vdevice.inpolygon = 1;
  596.     vdevice.fill = polymodeflag;
  597.     numv = 0;
  598.     p[numv][V_X] = x;
  599.     p[numv][V_Y] = y;
  600.     p[numv][V_Z] = z;
  601.     p[numv][V_W] = 1.0;
  602. }
  603.  
  604. /*
  605.  * pmvi
  606.  *
  607.  *    The integer argument version of pmv.
  608.  */
  609. void
  610. pmvi(x, y, z)
  611.     Icoord    x, y, z;
  612. {
  613.     pmv((double)x, (double)y, (double)z);
  614. }
  615.  
  616. /*
  617.  * pmv2i
  618.  *
  619.  *    The integer argument version of pmv2.
  620.  */
  621. void
  622. pmv2i(x, y)
  623.     Icoord    x, y;
  624. {
  625.     pmv((double)x, (double)y, vdevice.cpW[V_Z]);
  626. }
  627.  
  628. /*
  629.  * pmvs
  630.  *
  631.  *    The integer argument version of pmv.
  632.  */
  633. void
  634. pmvs(x, y, z)
  635.     Scoord    x, y, z;
  636. {
  637.     pmv((double)x, (double)y, (double)z);
  638. }
  639.  
  640. /*
  641.  * pmv2s
  642.  *
  643.  *    The integer argument version of pmv2.
  644.  */
  645. void
  646. pmv2s(x, y)
  647.     Scoord    x, y;
  648. {
  649.     pmv((double)x, (double)y, vdevice.cpW[V_Z]);
  650. }
  651.  
  652. /*
  653.  * pmv2
  654.  *
  655.  *    set up a polygon which will be constructed by a series of
  656.  * move draws in x, y.
  657.  */
  658. void
  659. pmv2(x, y)
  660.     double    x, y;
  661. {
  662.     pmv(x, y, vdevice.cpW[V_Z]);
  663. }
  664.  
  665.  
  666. /*
  667.  * pdr
  668.  *
  669.  *    add another vertex to the polygon array
  670.  */
  671. void
  672. pdr(x, y, z)
  673.     Coord    x, y, z;
  674. {
  675.     char    buf[100];
  676.     Token    *t;
  677.  
  678.     numv++;
  679.  
  680.     if (numv >= MAXVERTS) {
  681.         sprintf(buf, "pdr: can't draw a polygon with more than %d vertices", MAXVERTS);
  682.         verror(buf);
  683.     }
  684.  
  685.     p[numv][V_X] = x;
  686.     p[numv][V_Y] = y;
  687.     p[numv][V_Z] = z;
  688.     p[numv][V_W] = 1.0;
  689. }
  690.  
  691. /*
  692.  * rpdr
  693.  *
  694.  *    relative polygon draw.
  695.  */
  696. void
  697. rpdr(dx, dy, dz)
  698.     Coord    dx, dy, dz;
  699. {
  700.     rpdr((vdevice.cpW[V_X] + dx), (vdevice.cpW[V_Y] + dy), (vdevice.cpW[V_Z] + dz));
  701. }
  702.  
  703. /*
  704.  * rpdr2
  705.  *
  706.  *    relative polygon draw - only (x, y).
  707.  */
  708. void
  709. rpdr2(dx, dy)
  710.     Coord    dx, dy;
  711. {
  712.     rpdr((vdevice.cpW[V_X] + dx), (vdevice.cpW[V_Y] + dy), vdevice.cpW[V_Z]);
  713. }
  714.  
  715. /*
  716.  * rpdri
  717.  *
  718.  *    relative polygon draw. Icoord version.
  719.  */
  720. void
  721. rpdri(dx, dy, dz)
  722.     Icoord    dx, dy, dz;
  723. {
  724.     rpdr((vdevice.cpW[V_X] + dx), (vdevice.cpW[V_Y] + dy), (vdevice.cpW[V_Z] + dz));
  725. }
  726.  
  727. /*
  728.  * rpdr2i
  729.  *
  730.  *    relative polygon draw - only (x, y). Icoord version.
  731.  */
  732. void
  733. rpdr2i(dx, dy)
  734.     Icoord    dx, dy;
  735. {
  736.     rpdr((vdevice.cpW[V_X] + dx), (vdevice.cpW[V_Y] + dy), vdevice.cpW[V_Z]);
  737. }
  738.  
  739. /*
  740.  * rpdrs
  741.  *
  742.  *    relative polygon draw. Icoord version.
  743.  */
  744. void
  745. rpdrs(dx, dy, dz)
  746.     Scoord    dx, dy, dz;
  747. {
  748.     rpdr((vdevice.cpW[V_X] + dx), (vdevice.cpW[V_Y] + dy), (vdevice.cpW[V_Z] + dz));
  749. }
  750.  
  751. /*
  752.  * rpdr2s
  753.  *
  754.  *    relative polygon draw - only (x, y). Scoord version.
  755.  */
  756. void
  757. rpdr2s(dx, dy)
  758.     Scoord    dx, dy;
  759. {
  760.     rpdr((vdevice.cpW[V_X] + dx), (vdevice.cpW[V_Y] + dy), vdevice.cpW[V_Z]);
  761. }
  762.  
  763. /*
  764.  * rpmv
  765.  *
  766.  *    relative polygon move.
  767.  */
  768. void
  769. rpmv(dx, dy, dz)
  770.     Coord    dx, dy, dz;
  771. {
  772.     pmv((vdevice.cpW[V_X] + dx), (vdevice.cpW[V_Y] + dy), (vdevice.cpW[V_Z] + dz));
  773. }
  774.  
  775. /*
  776.  * rpmv2
  777.  *
  778.  *    relative polygon move - only (x, y).
  779.  */
  780. void
  781. rpmv2(dx, dy)
  782.     Coord    dx, dy;
  783. {
  784.     pmv((vdevice.cpW[V_X] + dx), (vdevice.cpW[V_Y] + dy), vdevice.cpW[V_Z]);
  785. }
  786.  
  787. /*
  788.  * rpmvi
  789.  *
  790.  *    relative polygon move. Icoord version.
  791.  */
  792. void
  793. rpmvi(dx, dy, dz)
  794.     Icoord    dx, dy, dz;
  795. {
  796.     pmv((vdevice.cpW[V_X] + dx), (vdevice.cpW[V_Y] + dy), (vdevice.cpW[V_Z] + dz));
  797. }
  798.  
  799. /*
  800.  * rpmv2i
  801.  *
  802.  *    relative polygon move - only (x, y). Icoord version.
  803.  */
  804. void
  805. rpmv2i(dx, dy)
  806.     Icoord    dx, dy;
  807. {
  808.     pmv((vdevice.cpW[V_X] + dx), (vdevice.cpW[V_Y] + dy), vdevice.cpW[V_Z]);
  809. }
  810.  
  811. /*
  812.  * rpmvs
  813.  *
  814.  *    relative polygon move. Icoord version.
  815.  */
  816. void
  817. rpmvs(dx, dy, dz)
  818.     Scoord    dx, dy, dz;
  819. {
  820.     pmv((vdevice.cpW[V_X] + dx), (vdevice.cpW[V_Y] + dy), (vdevice.cpW[V_Z] + dz));
  821. }
  822.  
  823. /*
  824.  * rpmv2s
  825.  *
  826.  *    relative polygon move - only (x, y). Scoord version.
  827.  */
  828. void
  829. rpmv2s(dx, dy)
  830.     Scoord    dx, dy;
  831. {
  832.     pmv((vdevice.cpW[V_X] + dx), (vdevice.cpW[V_Y] + dy), vdevice.cpW[V_Z]);
  833. }
  834.  
  835. /*
  836.  * pdri
  837.  *
  838.  *    The integer argument version of pdr.
  839.  */
  840. void
  841. pdri(x, y, z)
  842.     Icoord    x, y, z;
  843. {
  844.     pdr((double)x, (double)y, (double)z);
  845. }
  846.  
  847. /*
  848.  * pdr2i
  849.  *
  850.  *    The integer argument version of pdr2.
  851.  */
  852. void
  853. pdr2i(x, y)
  854.     Icoord    x, y;
  855. {
  856.     pdr((double)x, (double)y, vdevice.cpW[V_Z]);
  857. }
  858.  
  859. /*
  860.  * pdrs
  861.  *
  862.  *    The short argument version of pdr.
  863.  */
  864. void
  865. pdrs(x, y)
  866.     Scoord    x, y;
  867. {
  868.     pdr((double)x, (double)y, vdevice.cpW[V_Z]);
  869. }
  870.  
  871. /*
  872.  * pdr2s
  873.  *
  874.  *    The short argument version of pdr2.
  875.  */
  876. void
  877. pdr2s(x, y)
  878.     Scoord    x, y;
  879. {
  880.     pdr((double)x, (double)y, vdevice.cpW[V_Z]);
  881. }
  882.  
  883. /*
  884.  * pdr2
  885.  *
  886.  *    add another vertex to the polygon array
  887.  */
  888. void
  889. pdr2(x, y)
  890.     double    x, y;
  891. {
  892.     pdr(x, y, vdevice.cpW[V_Z]);
  893. }
  894.  
  895. /*
  896.  * pclos
  897.  *
  898.  *    draw the polygon started by the above.
  899.  */
  900. void
  901. pclos()
  902. {
  903.     double    lstx, lsty, lstz;
  904.     Vector    result;
  905.     int    i, j;
  906.     Token    *tok;
  907.  
  908.     if (!vdevice.initialised)
  909.         verror("pclos: vogl not initialised");
  910.  
  911.     vdevice.inpolygon = 0;
  912.  
  913.     if (vdevice.inobject) {
  914.         tok = newtokens(2 + 3 * (numv + 1));
  915.         tok[0].i = POLYF;
  916.         tok[1].i = numv + 1;
  917.         for (i = 0, j = 2; i <= numv; i++, j += 3) {
  918.             tok[j + V_X].f = p[i][V_X];
  919.             tok[j + V_Y].f = p[i][V_Y];
  920.             tok[j + V_Z].f = p[i][V_Z];
  921.         }
  922.  
  923.         return;
  924.     }
  925.  
  926.     lstx = p[numv][V_X];
  927.     lsty = p[numv][V_Y];
  928.     lstz = p[numv][V_Z];
  929.  
  930.     numv++;
  931.  
  932.     for (i = 0; i < numv; i++) {
  933.         multvector(result, p[i], vdevice.transmat->m);
  934.         p[i][V_X] = result[V_X];
  935.         p[i][V_Y] = result[V_Y];
  936.         p[i][V_Z] = result[V_Z];
  937.         p[i][V_W] = result[V_W];
  938.     }
  939.  
  940.     dopoly(numv);
  941.  
  942.     vdevice.cpW[V_X] = lstx;
  943.     vdevice.cpW[V_Y] = lsty;
  944.     vdevice.cpW[V_Z] = lstz;
  945. }
  946.  
  947. /*
  948.  * checkbacki
  949.  *
  950.  *    Checks if a transformed polygon is backfacing or not.
  951.  */
  952. static    int
  953. checkbacki()
  954. {
  955.  
  956. #ifdef    PC    /*    Only has 16 bit ints */
  957. #define    BACKFACE(z)    (clockwise ? ((z) <= 0L) : ((z) > 0L))
  958.     long    z;
  959. #else
  960. #define    BACKFACE(z)    (clockwise ? ((z) <= 0) : ((z) > 0))
  961.     int    z;
  962. #endif
  963.  
  964.     int    x1, x2, y1, y2;
  965.  
  966.     x1 = ip1[1] - ip1[0];
  967.     x2 = ip1[2] - ip1[1];
  968.     y1 = ip2[1] - ip2[0];
  969.     y2 = ip2[2] - ip2[1];
  970.  
  971. #ifdef    PC
  972.     z = (long)x1 * (long)y2 - (long)y1 * (long)x2;
  973. #else
  974.     z = x1 * y2 - y1 * x2;
  975. #endif
  976.  
  977.     return(BACKFACE(z));
  978. }
  979.  
  980. /*
  981.  * The following routines are an implementation of the Sutherland - Hodgman
  982.  * polygon clipper, as described in "Reentrant Polygon Clipping"
  983.  * Communications of the ACM Jan 1974, Vol 17 No. 1.
  984.  */
  985. static void
  986. polyclip(n)
  987.     register    int    n;
  988. {
  989.     int    i;
  990.  
  991.     nout = 0;
  992.     for (i = 0; i < 6; i++)
  993.         first[i] = 1;
  994.  
  995.     for (i = 0; i < n; i++) 
  996.         shclip(p[i], 0);
  997.  
  998.     shclose(0);
  999. }
  1000.  
  1001. static void
  1002. shclip(Pnt, side)
  1003.     double    Pnt[4];
  1004.     int    side;
  1005. {
  1006.     double    P[4];
  1007.  
  1008.     if (side == 6) {
  1009.         ip1[nout] = WtoVx(Pnt);
  1010.         ip2[nout++] = WtoVy(Pnt);
  1011.     } else {
  1012.         copyvector(P, Pnt);
  1013.         if (first[side]) {
  1014.             first[side] = 0;
  1015.             copyvector(F[side], P);
  1016.         } else if (intersect(side, I, P)) {
  1017.             shclip(I, side + 1);
  1018.         }
  1019.         copyvector(S[side], P);
  1020.         if (visible(side)) 
  1021.             shclip(S[side], side + 1);
  1022.     }
  1023. }
  1024.  
  1025. static void
  1026. shclose(side)
  1027.     int    side;
  1028. {
  1029.     if (side < 6) {
  1030.         if (intersect(side, I, F[side]))
  1031.             shclip(I, side + 1);
  1032.  
  1033.         shclose(side + 1);
  1034.  
  1035.         first[side] = 1;
  1036.     }
  1037. }
  1038.  
  1039. static
  1040. intersect(side, Ip, Pnt)
  1041.     int    side;
  1042.     register    Vector    Ip, Pnt;
  1043. {
  1044.     register    double    wc1, wc2, a;
  1045.  
  1046.     switch (side) {
  1047.     case 0:        /* x - left */
  1048.         wc1 = Pnt[3] + Pnt[0];
  1049.         wc2 = S[side][3] + S[side][0];
  1050.         break;
  1051.     case 1:        /* x - right */
  1052.         wc1 = Pnt[3] - Pnt[0];
  1053.         wc2 = S[side][3] - S[side][0];
  1054.         break;
  1055.     case 2:        /* y - bottom */
  1056.         wc1 = Pnt[3] + Pnt[1];
  1057.         wc2 = S[side][3] + S[side][1];
  1058.         break;
  1059.     case 3:        /* y - top */
  1060.         wc1 = Pnt[3] - Pnt[1];
  1061.         wc2 = S[side][3] - S[side][1];
  1062.         break;
  1063.     case 4:        /* z - near */
  1064.         wc1 = Pnt[3] + Pnt[2];
  1065.         wc2 = S[side][3] + S[side][2];
  1066.         break;
  1067.     case 5:        /* z - far */
  1068.         wc1 = Pnt[3] - Pnt[2];
  1069.         wc2 = S[side][3] - S[side][2];
  1070.         break;
  1071.     default:
  1072.         verror("intersect: ridiculous side value");
  1073.     }
  1074.  
  1075.     if (wc1 * wc2 < 0.0) {    /* Both are opposite in sign - crosses */
  1076.         a = wc1 / (wc1 - wc2);
  1077.         if (a < 0.0 || a > 1.0) {
  1078.             return(0);
  1079.         } else {
  1080.             Ip[0] = Pnt[0] + a * (S[side][0] - Pnt[0]);
  1081.             Ip[1] = Pnt[1] + a * (S[side][1] - Pnt[1]);
  1082.             Ip[2] = Pnt[2] + a * (S[side][2] - Pnt[2]);
  1083.             Ip[3] = Pnt[3] + a * (S[side][3] - Pnt[3]);
  1084.             return(1);
  1085.         }
  1086.     }
  1087.     return(0);
  1088. }
  1089.  
  1090. static
  1091. visible(side)
  1092.     int    side;
  1093. {
  1094.     double    wc;
  1095.  
  1096.     switch (side) {
  1097.     case 0:        /* x - left */
  1098.         wc = S[side][3] + S[side][0];
  1099.         break;
  1100.     case 1:        /* x - right */
  1101.         wc = S[side][3] - S[side][0];
  1102.         break;
  1103.     case 2:        /* y - bottom */
  1104.         wc = S[side][3] + S[side][1];
  1105.         break;
  1106.     case 3:        /* y - top */
  1107.         wc = S[side][3] - S[side][1];
  1108.         break;
  1109.     case 4:        /* z - near */
  1110.         wc = S[side][3] + S[side][2];
  1111.         break;
  1112.     case 5:        /* z - far */
  1113.         wc = S[side][3] - S[side][2];
  1114.         break;
  1115.     default:
  1116.         verror("visible: ridiculous side value");
  1117.     }
  1118.  
  1119.     return(wc >= 0.0);
  1120. }
  1121.  
  1122. /*
  1123.  * bgnpolygon
  1124.  *
  1125.  *    Set a flag so that we know what to do with v*() calls.
  1126.  */
  1127. void
  1128. bgnpolygon()
  1129. {
  1130.     if (vdevice.bgnmode != NONE)
  1131.         verror("vogl: bgnpolygon mode already belongs to some other bgn routine");
  1132.  
  1133.     vdevice.bgnmode = VPOLY;
  1134.     vdevice.fill = polymodeflag;
  1135.     vdevice.save = 1;
  1136.     vdevice.inpolygon = 1;
  1137. }
  1138.  
  1139. /*
  1140.  * endpolygon
  1141.  *
  1142.  *    Set a flag so that we know what to do with v*() calls.
  1143.  */
  1144. void
  1145. endpolygon()
  1146. {
  1147.     pclos();
  1148.  
  1149.     vdevice.bgnmode = NONE;
  1150.     vdevice.fill = 0;
  1151.     vdevice.inpolygon = 0;
  1152.     vdevice.save = 0;
  1153. }
  1154.